#include "memory_management.h"

#ifdef __cplusplus
extern "C" {
#endif

#include "misc.h"

#if !defined(USE_TFSIM) && !defined(USE_NATIVE)
#error "You must compile with either USE_NATIVE or USE_TFSIM"
#endif

#ifdef USE_TFSIM
#include <tf_xm.h>
#include <tf_mem.h>
#include <tf_common.h>
#include <tf_mm_cons.h>
#endif

#ifdef USE_NATIVE
#include "native_shm.h"
#endif

void * dfrt_mem_malloc( size_t s ) {
#ifdef USE_TFSIM
    return tf_mem_alloc_malloc( s );
#elif defined(USE_NATIVE)
    return native_shm_malloc(s);
#endif
}

void dfrt_mem_free( void * ptr ) {
#ifdef USE_TFSIM
    tf_mm_alloc_free(ptr);
#elif defined(USE_NATIVE)
    native_shm_free(ptr);
#endif


}

bool dfrt_mem_try_exclusive_acquire( void * ptr, size_t size) {
#ifdef USE_TFSIM
    return tf_mm_cons_try_exclusive_acquire(ptr,size);
#elif defined(USE_NATIVE)
    return native_shm_try_acquire(ptr,size,true);
#endif
}

void dfrt_mem_blocking_exclusive_acquire( void * ptr, size_t size) {
#ifdef USE_TFSIM
    tf_mm_cons_exclusive_acquire(ptr,size);
#elif defined(USE_NATIVE)
    native_shm_blocking_acquire(ptr,size,true);
#endif
}


bool dfrt_mem_try_shared_acquire( void * ptr, size_t size){
#ifdef USE_TFSIM
    return tf_mm_cons_try_shared_acquire(ptr,size);
#elif defined(USE_NATIVE)
    return native_shm_try_acquire(ptr,size,false);
#endif
}
void dfrt_mem_blocking_shared_acquire( void * ptr, size_t size) {
#ifdef USE_TFSIM
    tf_mm_cons_shared_acquire(ptr,size);
#elif defined(USE_NATIVE)
    native_shm_blocking_acquire(ptr,size,false);
#endif
}

void * dfrt_mem_get_global() {
#ifdef USE_TFSIM
    return tf_mem_get_global();
#elif defined(USE_NATIVE)
    return native_shm_get_global();
#endif
}
void dfrt_mem_set_global(void * ptr){
#ifdef USE_TFSIM
    tf_mem_set_global(ptr);
#elif defined(USE_NATIVE)
    native_shm_set_global(ptr);
#endif
}


// Size argument is unnecessary.
bool dfrt_mem_try_upgrade( void * ptr, size_t size){
#ifdef USE_TFSIM
    return tf_mm_cons_try_upgrade_acquire(ptr);
#elif defined(USE_NATIVE)
    return native_shm_try_acquire(ptr,size,true);
#endif
}


void dfrt_mem_blocking_upgrade( void * ptr, size_t size) {
#ifdef USE_TFSIM
    tf_mm_cons_upgrade_acquire(ptr);
#elif defined(USE_NATIVE)
    native_shm_blocking_acquire(ptr,size,true);
#endif
}

void dfrt_mem_release(void * ptr) {
#ifdef USE_TFSIM
    tf_mm_cons_release(ptr);
#elif defined(USE_NATIVE)
    native_shm_release(ptr);
#endif
}


bool dfrt_mem_async_acquire(void * vptr, size_t size, bool exclusive) {
#ifdef USE_TFSIM
#error "Unsupported."
#elif defined(USE_NATIVE)
    return native_shm_async_acquire(vptr, size, exclusive);
#endif
}
bool dfrt_mem_next_rls( struct dfrt_mem_release_mesg * msgbuf ) {
#ifdef USE_TFSIM
#error "Unsupported."
#elif defined(USE_NATIVE)
    return native_shm_next_rls(msgbuf);
#endif
}

#ifdef __cplusplus
}
#endif
